package br.mikhas.lab.scanner;

import java.util.ArrayList;
import java.util.Collections;

public class State {

	private static int stateCount = 0;

	private String tokenType;

	private final int id;

	/**
	 * Flags the transitions list is trimmed.
	 * <p>
	 * Used to reduce the amount of memory alocated to unused arrays
	 */
	private boolean trimmed = false;

	private ArrayList<Transition> transitions = new ArrayList<Transition>();

	public State() {
		this.id = ++stateCount;
	}

	/**
	 * Check if the state is final.
	 * <p>
	 * An state is final when it returns a token definition
	 * 
	 * @return <tt>true</tt> if this state is final and returns a Token
	 *         definition
	 */
	public boolean isFinalState() {
		return this.tokenType != null && !this.tokenType.isEmpty();
	}

	/**
	 * Sets the name of the token type
	 * 
	 * @param tokenType
	 */
	public void setTokenType(String tokenType) {
		this.tokenType = tokenType;
	}

	/**
	 * Adds a new transition to this state.
	 * <p>
	 * A transition defines the next states from the current state.
	 * 
	 * @param transition
	 */
	public void addTransition(Transition transition) {
		trimmed = false;
		transitions.add(transition);

		if (transitions.size() > 1)
			Collections.sort(transitions);
	}

	/**
	 * Gets the next state
	 * 
	 * @param c
	 * @return
	 */
	public State nextState(char c) {
		if (!trimmed) {
			transitions.trimToSize();
			trimmed = true;
		}

		int i = transitions.size();
		for (int j = 0; j < i; j++) {
			Transition t = transitions.get(j);

			if (t.accept(c))
				return t.getNextState();
		}

		return null;
	}

	public String getTokenType() {
		return this.tokenType;
	}

	@Override
	public String toString() {
		return "STATE " + id + (isFinalState() ? ": " + tokenType : "");
	}
}
